#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
@Project ：pyqt5_device 
@File    ：t2_client.py
@IDE     ：PyCharm 
@Author  ：Toby
@Date    ：2023/9/15 17:57 
'''

import json
import logging
import threading
import time

import paho.mqtt.client as mqtt
from jsonpath import jsonpath

from mydb import MySqlDb
from util.cose import CoseDecoder, CoseEncoder

logger = logging.getLogger(__name__)

CODESTATR = "R"
CODESTOP = "N"
_TIMESLEEP = 1


def bytetostr(by):
    return str(by, encoding="utf-8")


myset = set()


# 创建一个MQTT客户端类，用于连接和处理MQTT消息
class T2Thread(threading.Thread):

    def __init__(self, content):
        super(T2Thread, self).__init__()

        self.mngid = str.split(content, ',')[0]
        self.device_type = str.split(content, ',')[1]
        logger.info(f"mngid-->{self.mngid},device_type-->{self.device_type} ")

        self.db = MySqlDb()

    def run(self):
        # 在这里写入你的MQTT连接和订阅代码
        def on_connect(client, userdata, flags, rc):
            print("Connected with result code " + str(rc))
            if rc == 0:
                print("Connected to MQTT OK!, Will Subs message :")
            else:
                print("Failed to connect, return code %d\n", rc)

        def on_message(client, userdata, msg):
            print(f"on_message----->{msg.topic}")

            topicname = msg.topic
            mngId = topicname.split('/', 4)[2]
            order = topicname.split('/', 4)[3]
            global passwordId, orderId, direction, msgSN, reg_msgSN
            msgSN = 0
            reg_msgSN = 0

            if order == '8001':  # 注册
                sql = "select * from t_charge_pile where mngId=" + '"' + mngId + '"' + " limit 1;"
                ress = self.db.select_sql(sql)
                # 解码 接收到的消息
                payload = CoseDecoder.decode_with_aes_ccm_16_64_128(payload=msg.payload)
                print(f"接收到服务器的注册应答消息 order:8001  :{payload}")
                mngid = ress[0]['mngId']
                boxCode = ress[0]['boxCode']
                model = ress[0]['model']


            elif order == "0000":  # 下单
                #     topic[/T1/4ead9328595f/0000]
                #     message[{"direction":1,"door1":1,"msgSN":5,"orderId":1759728085,"passwordId":766682,
                #     "passwordIn":320381,"passwordOut":859612,"userId":205203515,"vehicleType":1}]
                # 解码 接收到的消息
                payload = CoseDecoder.decode_with_aes_ccm_16_64_128(payload=msg.payload)
                print(print(f"order:0000 payload ;{payload}"))
                passwordId = payload['passwordId']
                orderId = payload['orderId']
                msgSN = payload['msgSN']
                print(f" 0000 orderId:{orderId},passwordId: {passwordId}")

                #  /T1/4ead93285951/0001 mac: 4ead93285951 message : {"msgSN":226,"errorCode":0}
                topicname = "/T1/" + mngId + "/0001"
                payload = {"msgSN": msgSN, "errorCode": 0}
                pl = CoseEncoder.encode_with_aes_ccm_16_64_128(payload=payload)
                self.t2publish(self.client, topicname, pl)

                time.sleep(_TIMESLEEP)
                # 发送门的结果
                topicname = "/T1/" + mngId + "/8004"
                # message : {"timeStamp":1697430190,"door2":0,"orderId":-36059327,"door1":1,"msgSN":54,"direction":1}

                starttime = int(time.time())
                direction = 1
                payload = {"timeStamp": starttime, "door2": 0, "orderId": orderId, "door1": 1, "msgSN": msgSN,
                           "direction": direction}
                pl = CoseEncoder.encode_with_aes_ccm_16_64_128(payload=payload)
                self.t2publish(self.client, topicname, pl)
                time.sleep(_TIMESLEEP)


            elif order == "8005":
                # 解码 接收到的消息
                # publish to topic[/T1/4ead93285951/8005] message[{"errorCode":0,"msgSN":226}]
                payload = CoseDecoder.decode_with_aes_ccm_16_64_128(payload=msg.payload)
                print(f"order:8005 >>{payload}")
                msgSN = payload['msgSN']
                time.sleep(_TIMESLEEP)

                # /T1/4ead93285951/8006 mac: 4ead93285951 message : {"orderKey":0,"method":1,"orderId":793191631,
                # "msgSN":298,"errorCode":0,"brakeNumber":1,"methodDesc":0,"nfcNumber":0,"passwordId":766260,"timeStamp1":1697277388,
                # "timeStamp2":0,"timeStamp3":0,"vehicleType":1,"timeStamp4":0}
                if direction == 1:
                    topicname = "/T1/" + mngId + "/8006"
                    payload = {"orderKey": 0, "method": 1, "orderId": orderId,
                               "msgSN": msgSN, "errorCode": 0, "brakeNumber": 1, "methodDesc": 0, "nfcNumber": 0,
                               "passwordId": passwordId,
                               "timeStamp1": int(time.time()),
                               "timeStamp2": 0, "timeStamp3": 0, "vehicleType": 1, "timeStamp4": 0}
                    payload = CoseEncoder.encode_with_aes_ccm_16_64_128(payload=payload)
                    self.t2publish(self.client, topicname, payload)
                    time.sleep(_TIMESLEEP)

                elif direction == 2:
                    # receive topic : /T1/4ead93285951/8006 mac: 4ead93285951
                    # message : {"orderKey":0,"method":1,"orderId":2095380837,"msgSN":4,"errorCode":0,
                    # "brakeNumber":4,"methodDesc":0,"nfcNumber":0,"passwordId":766403,"timeStamp1":0,"timeStamp2":0,"timeStamp3":0,"vehicleType":1,"timeStamp4":1697434770}
                    topicname = "/T1/" + mngId + "/8006"
                    payload = {"orderKey": 0, "method": 1, "orderId": orderId,
                               "msgSN": msgSN, "errorCode": 0, "brakeNumber": 4, "methodDesc": 0, "nfcNumber": 0,
                               "passwordId": passwordId,
                               "timeStamp1": 0,
                               "timeStamp2": 0, "timeStamp3": 0, "vehicleType": 1, "timeStamp4": int(time.time())}
                    payload = CoseEncoder.encode_with_aes_ccm_16_64_128(payload=payload)
                    self.t2publish(self.client, topicname, payload)
                    time.sleep(_TIMESLEEP)


            elif order == "8007":  ##8006 对应下单的消息，接收后进行处理
                # publish to topic[/T1/4ead93285951/8007] message[{"errorCode":0,"msgSN":298}]
                payload = CoseDecoder.decode_with_aes_ccm_16_64_128(payload=msg.payload)
                print(f"order:8007 >>>{payload}")
                msgSN = payload['msgSN']


            elif order == "0002":  # 出场
                # publish to topic[/T1/4ead93285951/0002] message[{"direction":2,"orderId":2095380837,"passwordId":766403}]
                payload = CoseDecoder.decode_with_aes_ccm_16_64_128(payload=msg.payload)
                print(f"order:0002 ;{payload}")
                orderId = payload["orderId"]
                passwordId = payload["passwordId"]
                if msgSN:
                    msgSN = msgSN
                else:
                    msgSN = reg_msgSN
                # receive topic : /T1/4ead93285951/0003 mac: 4ead93285951 message : {"msgSN":4,"errorCode":0}
                topicname = "/T1/" + mngId + "/0003"
                payload = {"msgSN": msgSN, "errorCode": 0}
                payload = CoseEncoder.encode_with_aes_ccm_16_64_128(payload=payload)
                self.t2publish(self.client, topicname, payload)
                time.sleep(_TIMESLEEP)

                # receive topic : /T1/4ead93285951/8004 mac: 4ead93285951
                # message : {"timeStamp":1697434766,"door2":1,"orderId":2095380837,"door1":0,"msgSN":4,"direction":2}
                # 发送门的结果
                topicname = "/T1/" + mngId + "/8004"
                outtime = int(time.time())
                direction = 2
                payload = {"timeStamp": outtime, "door2": 1, "orderId": orderId, "door1": 0, "msgSN": msgSN,
                           "direction": direction}
                pl = CoseEncoder.encode_with_aes_ccm_16_64_128(payload=payload)
                self.t2publish(self.client, topicname, pl)
                time.sleep(_TIMESLEEP)

        def on_publish_callback(client, userdata, mid):
            print(client, userdata, mid)

        def on_subscribe_callback(client, userdata, mid, reasonCodes, *args):
            print(client, userdata, mid, reasonCodes)

        self.client = mqtt.Client(self.mngid)
        print("当前客户端 T2 ID:{}".format(bytetostr(self.client._client_id)))
        self.client.on_connect = on_connect
        self.client.on_message = on_message
        self.client.on_publish = on_publish_callback
        self.client.on_subscribe = on_subscribe_callback

        with open('./config.json', 'r', encoding='utf8')as fp:
            json_data = fp.read()
            json_data = json.loads(json_data)
            self.SERVER_HOST = jsonpath(json_data, "$.testsss.mqttbroker.SERVER_HOST")
            self.USER_NAME = jsonpath(json_data, "$.testsss.mqttbroker.USER_NAME")
            self.PASSWORD = jsonpath(json_data, "$.testsss.mqttbroker.PASSWORD")
            self.BIND_PORT = jsonpath(json_data, "$.testsss.mqttbroker.BIND_PORT")

        self.client.username_pw_set(self.USER_NAME[0], self.PASSWORD[0])
        self.client.connect(self.SERVER_HOST[0], self.BIND_PORT[0], 60)

        def submessage(client):
            # 对应的接收消息
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8023")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8011")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/0026")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/0014")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8001")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8005")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8007")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8003")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/0024")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8045")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8009")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/0002")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8027")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8029")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8031")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8099")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8017")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/8015")
            client.subscribe("/T1/" + bytetostr(self.client._client_id) + "/0000")

        def regdevice(client):
            # T2设备
            topict2 = "/T1/" + bytetostr(client._client_id) + "/8000"

            # T2 设备注册
            if self.device_type == '27':
                print(f" T2 device_type :‘{self.device_type}’")  # 859901
                payload = {
                    "primary": 9, "secondary": 1, "SPU": "T2-SPU", "model": "XLR_T2",
                    "hardwareVersion": "hc32f4a0_t2-(V1.0.0)-(V1.0.63)", "msgSN": 1,
                    "runningParametersHash": 0, "passwordHash": 0
                }
                # 加密
                pl = CoseEncoder.encode_with_aes_ccm_16_64_128(payload=payload)
                # 解密
                pl2 = CoseDecoder.decode_with_aes_ccm_16_64_128(payload=pl)
                self.t2publish(client, topict2, pl)

        # Todo 订阅消息
        submessage(self.client)
        # todo 注册设备
        regdevice(self.client)

        self.client.loop_forever()

    def t2publish(self, client, topname, payload):
        info = client.publish(topname, payload)
        mid = info.mid
        print(f" T2 client publish mid-->{mid}  ,publish over")
